#ifndef _GSTRUNTIMEEXCEPTION_H_
#define _GSTRUNTIMEEXCEPTION_H_


#define GSTRUNTIMEERROR 1
#define GSTOUTOFRANGE 2
#define GSTSQLERROR 3
#define GSTCASTERROR 4
#define GSTSQLNULLERROR 5
#define GSTSQLEMPTYERROR 6
#define GSTINCOMPATIBLE 7
#define GSTLICENSEERROR 8
#define GSTTIMEOUT 9
#define GSTSRSINUSE 10
#define GSTINVALIDARG 11
#define GSTTOOFEWARGUMENTS 12
#define GSTINVALIDTYPE 13
#define GSTCOULDNOTCREATEGEO 14
#define GSTINVALIDDATABASE 15
#define GSTUNSUPPORTED 16
#define GSTNOGEOMETRY 17
#define GSTLOGFILEEXCEPTION 18
#define GSTFORMATERROR 19
#define GSTNOTFOUND 20
#define GSTNOTRANSFORM 21
#define BADPARAMETER 22
#define GEOMETRYISLOCKED 23
#define INVALIDFORMATSTRING 24
#define GEOMETRYIDUNKNOWN 25
#define TRANSFORMERROR 26
#define EMPTYGEOMETRY 27
#define GSTINCOMPATIBLEFEATURE 28
#define GEOMETRYISLOCKEDINAREA 29
#define BORDERCONSTRAINTVIOLATED 30
#define FEATUREISLOCKED 31
#define INTERSECTIONNORESULT 32
#define RTREEINDEXALREADYEXISTS 33

#define EXCEPTIONSEPARATOR char(30)


#include <exception>
#include <stdexcept>
#include <string>
#include <sstream>
#include <vector>

#include <boost/current_function.hpp>
#include <boost/lexical_cast.hpp>

namespace GST {
namespace exceptions {

inline std::string methodName(const std::string& prettyFunction)
{
	size_t colons = prettyFunction.find("::");
	size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1;
	size_t end = prettyFunction.rfind("(") - begin;

	return prettyFunction.substr(begin,end) + "()";
}

#define __METHOD_NAME__ GST::exceptions::methodName(BOOST_CURRENT_FUNCTION)

/** 
	\brief To be thrown on runtime errors.
	*/
class GSTRuntimeException 
: public std::runtime_error
{
protected:
	//### member ###
	std::string _msg;
	const unsigned int _number;
	std::string _GSTprefix;
	std::string callstack;
	std::vector<std::string> attachments;
			
public:
	//### public methods ###
	/** 	
	* exception caller interface (c'tor used by throw'er of exception)
	*
		@param classname	name of the class the exception is thrown
		@param methode		name of the methode the exception is thrown
		@param msg			gives information about the exception (e.g. reason why or possible solution text to be read by human.)
		@param number		number of GST Exception */
	GSTRuntimeException( const std::string & throwLocation, const std::string& msg, const unsigned int& number=GSTRUNTIMEERROR) 
		: std::runtime_error( msg.c_str() )
		, _msg(msg)
		, _number(number)
	{
		this->preparePrefix();
		//this->callstack = caller;
	}

	//### public methods ###
	/** 
	* exception receiver interface (c'tor used by catch'er of exception)
	*
		@param encodedException string of encoded exception */
	GSTRuntimeException(const std::string & encodedException, const unsigned int& number=GSTRUNTIMEERROR) 
		: std::runtime_error( "" )
		, _number(number)
	{
		this->preparePrefix(); 				

		if(!encodedException.empty()) {
			this->decodeMessage(encodedException);
		}
	}

	virtual ~GSTRuntimeException() throw()
	{
	}

	void preparePrefix()
	{
		std::stringstream str;
		str << "GSTERR-";
		char prev = str.fill();
		str.fill ('0');
		std::streamsize previ = str.width();
		str.width (6);
		str << this->_number;
		str.fill(prev);
		str.width(previ);
		str << ": ";
		this->_GSTprefix = str.str();
	}
			
	/** @return message's text */
	const std::string getMessage() const 
	{
		return this->_msg;
	}

	virtual std::string encodeMessage() const
	{
		std::string result;
		//encode: exception header + message
		result = this->_GSTprefix+this->_msg+EXCEPTIONSEPARATOR;
		//encode: attachment
		for(const std::string & attachment : this->attachments)
		{
			result += attachment+EXCEPTIONSEPARATOR;	
		}

		return result;
	}

	virtual void decodeMessage(const std::string& db_errormessage)
	{
		size_t pos = db_errormessage.find("GSTERR");
		if ( pos != std::string::npos ) // let's handle some more specific exceptions otherwise keep going
		{
			//code number
			std::string gstErr(db_errormessage.substr(pos,13));

			//message
			size_t endPos = db_errormessage.find(EXCEPTIONSEPARATOR);					
			this->_msg = db_errormessage.substr(pos+14, endPos-pos-14);

			//attachments
			attachments.clear();
			size_t oldPos = endPos+1;
			endPos = db_errormessage.find(EXCEPTIONSEPARATOR, oldPos);	
			while(oldPos != endPos && endPos != std::string::npos)
			{ 
				attachments.push_back( db_errormessage.substr(oldPos, endPos-oldPos) );

				oldPos = endPos+1;
				endPos = db_errormessage.find(EXCEPTIONSEPARATOR, oldPos);
			}
		}
		else
		{
			this->_msg = db_errormessage;
		}
	}

	static unsigned int getExceptionCode(const std::string& db_errormessage)
	{
		size_t pos = db_errormessage.find("GSTERR");
		if ( pos != std::string::npos ) // let's handle some more specific exceptions otherwise keep going
		{
			std::string gstErr(db_errormessage.substr(pos,13));
			std::stringstream str(gstErr.substr(7));
			unsigned int err;
			str >> err;

			return err;
		}

		return (unsigned int)GSTRUNTIMEERROR; 
	}
			
	/** 
		@return to location the exception was thrown like this:<br>
		\verbatim classname::methodename \endverbatim */
	const std::string getThrowLocation() const 
	{ 
		return this->callstack;	
	}

	/** overriden std::exception output */
	virtual const char * what() const throw() 
	{
		return this->_msg.empty() ? "No message available" : this->_msg.c_str();
	}
			
	virtual void appendToStack(const std::string& add)
	{
		this->callstack += "\n" + add;
	}

	virtual void appendToMessage(  const std::string & msg )
	{
		this->_msg += " " + msg;
	}
};// class

class GSTOutOfRange
	: public GSTRuntimeException
{
public:
	///catcher interface
	GSTOutOfRange(const std::string & encodedMessage)
		: GSTRuntimeException( "", GSTOUTOFRANGE )
	{
	}

	///thrower interface
	GSTOutOfRange(const std::string & throwLocation, const std::string& container) 
		: GSTRuntimeException( throwLocation, "", GSTOUTOFRANGE)
	{
		_msg = container + " is out of range.";
	}
};
		
/**
	* To be thrown on GST Storage side
	*/
class GSTSQLError
	: public GSTRuntimeException
{
public:
	long error_code;

	///catcher interface
	GSTSQLError(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTSQLERROR )
	{
		this->attachment2ExceptionData();
	}

	//thrower interface
	GSTSQLError(const std::string & throwLocation, const std::string & msg, const std::string& sql, long exec_err_code)
		: GSTRuntimeException(throwLocation,"", GSTSQLERROR)
		, error_code(exec_err_code)
	{
		std::stringstream smsg;
		smsg << "Error in query: \"" << sql << "\" (exec error code: "<< exec_err_code <<").";
		if(!msg.empty())
			smsg << " Message: "<<msg;
				
		_msg = smsg.str();

		//append data
		this->attachments.push_back( boost::lexical_cast<std::string>(error_code) );
	}

	void attachment2ExceptionData()
	{
		if(this->attachments.size() > 0)
		{
			try
			{
				std::string str = this->attachments.back();
				this->error_code = boost::lexical_cast<long>(str);

				return;
			}
			catch (const boost::bad_lexical_cast &)	{						
			} 					
		}

		this->error_code = -1;
		this->_msg += " (error decoding error_code)";
	}
			
};

/**
	* Obsolete?
	*/
class GSTCastError
	: public GSTRuntimeException
{
public:
	///catcher interface
	GSTCastError(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTCASTERROR )
	{
	}

	//thrower interface
	GSTCastError(const std::string & throwLocation, const std::string& from, const std::string& to)
		: GSTRuntimeException(throwLocation, "", GSTCASTERROR)
	{
		std::stringstream smsg;
		smsg << "Cast error from \"" << from << "\" to \""<< to <<"\".";				
		_msg = smsg.str();
	}
			
};

/* ClientQueryError -> replace by SQLSyntaxError(RDBDriverInterface.h) 
*/

/* ClientConnectionClosed -> replace by ConnectionTerminated(RDBDriverInterface.h)
*/
	
class GSTSQLNULLException
	: public GSTSQLError
{
public:
	///catcher interface
	GSTSQLNULLException(const std::string & encodedMessage)
		: GSTSQLError( encodedMessage )
	{
	}

	//thrower interface
	GSTSQLNULLException(const std::string & throwLocation, const std::string& sql, int spi_exec_err_code) 
		: GSTSQLError(throwLocation, "", sql, spi_exec_err_code)
	{}
};

class GSTSQLEmptyResultset
	: public GSTSQLError
{
public:
	///catcher interface
	GSTSQLEmptyResultset(const std::string & encodedMessage)
		: GSTSQLError( encodedMessage )
	{
	}

	//thrower interface
	GSTSQLEmptyResultset(const std::string & throwLocation, const std::string& sql, int spi_exec_err_code)
		: GSTSQLError(throwLocation, "", sql, spi_exec_err_code)
	{}
};
		
class GSTIncompatibleInsert
	: public GSTRuntimeException
{
public:
	///catcher interface
	GSTIncompatibleInsert(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTINCOMPATIBLE )
	{
	}

	//thrower interface
	GSTIncompatibleInsert(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GSTINCOMPATIBLE)
	{}
};


class GSTFeatureIncompatibleToFeatureclass
	: public GSTRuntimeException
{
public:
	///catcher interface
	GSTFeatureIncompatibleToFeatureclass(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTINCOMPATIBLEFEATURE )
	{
	}

	//thrower interface
	GSTFeatureIncompatibleToFeatureclass(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GSTINCOMPATIBLEFEATURE)
	{}
};
		
class GSTLicenseError
	: public GSTRuntimeException
{
public:
	long error_code;

	///catcher interface
	GSTLicenseError(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTLICENSEERROR )
	{
		this->attachment2ExceptionData();
	}

	//thrower interface
	GSTLicenseError(const std::string & throwLocation, const std::string& msg, long exec_err_code)
		: GSTRuntimeException(throwLocation, msg, GSTLICENSEERROR), error_code(exec_err_code)
	{
		//append error_code to attachment
		this->attachments.push_back( boost::lexical_cast<std::string>(error_code) );
	}

	void attachment2ExceptionData()
	{
		if(this->attachments.size() > 0)
		{
			try
			{
				std::string atStr = this->attachments.back();
				this->error_code = boost::lexical_cast<long>(atStr);

				return;
			}
			catch (const boost::bad_lexical_cast &)	{						
			} 					
		}

		this->error_code = -1;
		this->_msg += " (error decoding error_code)";
	}
}; 

class GSTTransactionTimeout 
	: public GSTRuntimeException
{
public:
	///catcher interface
	GSTTransactionTimeout(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTTIMEOUT )
	{
	}

	//thrower interface
	explicit GSTTransactionTimeout(const std::string & throwLocation, const std::string & msg)
		: GSTRuntimeException(throwLocation, msg, GSTTIMEOUT)
	{}
};
		
class SRSStillInUseException
	: public GSTRuntimeException
{
public:
	typedef std::vector<std::string> ClassList;
	ClassList featureClassList;

	///catcher interface
	SRSStillInUseException(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTSRSINUSE )
	{
		this->attachment2ExceptionData();
	}

	//thrower interface
	SRSStillInUseException(const std::string & throwLocation, const std::string & message, const ClassList & featureClassList)
		: GSTRuntimeException(throwLocation,message, GSTSRSINUSE), featureClassList(featureClassList)
	{
		//append featureClassList to attachments
		for(const std::string & fc : featureClassList)
		{
			this->attachments.push_back(fc);
		}
	}
	virtual ~SRSStillInUseException() throw() {
		// needs to be here because of nontrivial destructor of ClassList
		// otherwise we'll have "specification of overriding function
		// is more lax than base version"
	}

	void attachment2ExceptionData()
	{
		if(this->attachments.size() > 0)
		{
			for(const std::string & at : attachments)
			{
				this->featureClassList.push_back(at);
			}

			//stop here
			return;
		}

		//inform in bad case
		this->_msg += " (error decoding featureClassList)";
	}


};

class GSTInvalidArgument
	: public GSTRuntimeException
{
public:	
	///catcher interface
	GSTInvalidArgument(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTINVALIDARG )
	{}

	//thrower interface
	GSTInvalidArgument(const std::string & throwLocation, const std::string& msg)
	: GSTRuntimeException(throwLocation, msg, GSTINVALIDARG)
	{}
};

class GSTTooFewArguments
	: public GSTRuntimeException
{
public:	
	///catcher interface
	GSTTooFewArguments(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTTOOFEWARGUMENTS )
	{}

	//thrower interface
	GSTTooFewArguments(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GSTTOOFEWARGUMENTS)
	{}

};

class GSTInvalidType
	: public GSTRuntimeException
{
public:	
	///catcher interface
	GSTInvalidType(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTINVALIDTYPE )
	{}

	//thrower interface
	GSTInvalidType(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GSTINVALIDTYPE)
	{}
};

class GSTCouldNotCreateGeometry
	: public GSTRuntimeException
{
public:	
	///catcher interface
	GSTCouldNotCreateGeometry(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTCOULDNOTCREATEGEO )
	{}

	//thrower interface
	GSTCouldNotCreateGeometry(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GSTCOULDNOTCREATEGEO)
	{}
};

class GSTInvalidDatabase
	: public GSTRuntimeException
{
public:	
	///catcher interface
	GSTInvalidDatabase(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTINVALIDDATABASE )
	{}

	//thrower interface
	GSTInvalidDatabase(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GSTINVALIDDATABASE)
	{}
};

class GSTUnsupported
	: public GSTRuntimeException
{
public:		 
	///catcher interface
	GSTUnsupported(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTUNSUPPORTED )
	{}

	//thrower interface
	GSTUnsupported(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GSTUNSUPPORTED)
	{}
};

class GSTNoGeometry
	: public GSTRuntimeException
{
public:	 
	///catcher interface
	GSTNoGeometry(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTNOGEOMETRY )
	{}

	//thrower interface
	GSTNoGeometry(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GSTNOGEOMETRY)
	{}
};
		
class EmptyGeometry
	: public GSTRuntimeException
{
public:	 
	///catcher interface
	EmptyGeometry(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, EMPTYGEOMETRY )
	{}

	//thrower interface
	EmptyGeometry(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, EMPTYGEOMETRY)
	{}
};

class GSTLogFileException
	: public GSTRuntimeException
{
public:	 
	///catcher interface
	GSTLogFileException(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTLOGFILEEXCEPTION )
	{}

	//thrower interface
	GSTLogFileException(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GSTLOGFILEEXCEPTION)
	{}
};

class GSTFormatError
	: public GSTRuntimeException
{
public:	 
	///catcher interface
	GSTFormatError(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTFORMATERROR )
	{}

	//thrower interface
	GSTFormatError(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GSTFORMATERROR)
	{}
};

class GSTNotFound
	: public GSTRuntimeException
{
public:	 
	///catcher interface
	GSTNotFound(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTNOTFOUND )
	{}

	//thrower interface
	GSTNotFound(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GSTNOTFOUND)
	{}
};
class GSTNoTransformAvailable
	: public GSTRuntimeException
{
public:	  
	///catcher interface
	GSTNoTransformAvailable(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GSTNOTRANSFORM )
	{}

	//thrower interface
	GSTNoTransformAvailable(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation ,msg, GSTNOTRANSFORM)
	{}
};

class BadParameter
	: public GSTRuntimeException
{
public:
	std::string parameterName;

	///catcher interface
	BadParameter(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, BADPARAMETER )
	{
		this->attachment2ExceptionData();
	}

	//thrower interface
	BadParameter(const std::string & throwLocation, const std::string& msg, const std::string& parameterName)
		: GSTRuntimeException(throwLocation, msg, BADPARAMETER)
		, parameterName(parameterName)
	{
		this->_msg += "(parameter: "+parameterName+")";

		//append parameterName to attachments
		this->attachments.push_back( parameterName );
	}

	virtual ~BadParameter() throw()
	{
	} 

	void attachment2ExceptionData()
	{
		if(this->attachments.size() > 0)
		{
			this->parameterName = this->attachments.back();

			//stop here
			return;
		}

		this->parameterName = "";
		this->_msg += " (error decoding parameterName)";
	}
};

class GeometryIsLocked
	: public GSTRuntimeException
{
public:
	///catcher interface
	GeometryIsLocked(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GEOMETRYISLOCKED )
	{}

	//thrower interface
	GeometryIsLocked(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, GEOMETRYISLOCKED)
	{
	}
	virtual ~GeometryIsLocked() throw()
	{
	}
};

class GeometryIsLockedInArea : public GSTRuntimeException
{
public:
	/// catcher interface
	GeometryIsLockedInArea(const std::string &encodedMessage)
		: GSTRuntimeException(encodedMessage, GEOMETRYISLOCKEDINAREA)
	{
	}

	// thrower interface
	GeometryIsLockedInArea(const std::string &throwLocation,
						   const std::string &msg)
		: GSTRuntimeException(throwLocation, msg, GEOMETRYISLOCKEDINAREA)
	{
	}
	virtual ~GeometryIsLockedInArea() throw()
	{
	}
};

class InvalidFormatString
	: public GSTRuntimeException
{
public:
	///catcher interface
	InvalidFormatString(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, INVALIDFORMATSTRING )
	{}

	//thrower interface
	InvalidFormatString(const std::string & throwLocation, const std::string& formatstring)
		: GSTRuntimeException(throwLocation,"", INVALIDFORMATSTRING)
	{
		this->_msg = "Output type "+formatstring+" is not registered.";
	}
};

class GeometryIdUnknown
	: public GSTRuntimeException
{
public:
	long geometryid;

	///catcher interface
	GeometryIdUnknown(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, GEOMETRYIDUNKNOWN )
	{
		this->attachment2ExceptionData();
	}

	//thrower interface
	GeometryIdUnknown(const std::string & throwLocation, const long& geometryid)
		: GSTRuntimeException(throwLocation, "", GEOMETRYIDUNKNOWN)
		, geometryid(geometryid)
	{
		this->_msg = "geometry with id="+boost::lexical_cast<std::string>(geometryid)+" does not exists.";

		//append geometryid to attachments
		this->attachments.push_back( boost::lexical_cast<std::string>(geometryid) );
	}

	void attachment2ExceptionData()
	{
		if(this->attachments.size() > 0)
		{
			try
			{
				std::string geometryIdStr = this->attachments.back();
				this->geometryid = boost::lexical_cast<long>(geometryIdStr);

				//stop here
				return;
			}
			catch (const boost::bad_lexical_cast &)	{						
			} 					
		}
				
		//inform in bad case
		this->geometryid = -1;
		this->_msg += " (error decoding geometryId)";
	}
};

class TransformError
	: public GSTRuntimeException
{
public:
	///catcher interface
	TransformError(const std::string & encodedMessage)
		: GSTRuntimeException( encodedMessage, TRANSFORMERROR )
	{}

	//thrower interface
	TransformError(const std::string & throwLocation, const std::string& msg)
		: GSTRuntimeException(throwLocation, msg, TRANSFORMERROR)
	{}
};

class BorderConstraintViolated : public GSTRuntimeException
{
public:
	/// catcher interface
	BorderConstraintViolated(const std::string &encodedMessage)
		: GSTRuntimeException(encodedMessage, BORDERCONSTRAINTVIOLATED)
	{
	}

	// thrower interface
	BorderConstraintViolated(const std::string &throwLocation,
							 const std::string &msg)
		: GSTRuntimeException(throwLocation, msg, BORDERCONSTRAINTVIOLATED)
	{
	}

	virtual ~BorderConstraintViolated() throw()
	{
	}
};

class FeatureIsLocked : public GSTRuntimeException
{
public:
	std::vector<int> lockedGeometryIds;

	/// catcher interface
	FeatureIsLocked(const std::string &encodedMessage)
		: GSTRuntimeException(encodedMessage, FEATUREISLOCKED)
	{
	}

	// thrower interface
	FeatureIsLocked(const std::string &throwLocation,
					const std::string &msg,
					const std::vector<int> & lockedGeometryIds)
		: GSTRuntimeException(throwLocation, msg, FEATUREISLOCKED)
		, lockedGeometryIds(lockedGeometryIds)
	{
	}

	virtual ~FeatureIsLocked() throw()
	{
	}

	
};

class IntersectionNoResult : public GSTRuntimeException
{
public:
	/// catcher interface
	IntersectionNoResult(const std::string &encodedMessage)
			: GSTRuntimeException(encodedMessage, INTERSECTIONNORESULT)
	{
	}

	// thrower interface
	IntersectionNoResult(const std::string &throwLocation, const std::string &msg)
			: GSTRuntimeException(throwLocation, msg, INTERSECTIONNORESULT)
	{
	}

	virtual ~IntersectionNoResult() throw()
	{
	}
};

class RtreeIndexAlreadyExists : public GSTRuntimeException
{
public:
	/// catcher interface
	RtreeIndexAlreadyExists(const std::string &encodedMessage)
			: GSTRuntimeException(encodedMessage, RTREEINDEXALREADYEXISTS)
	{
	}

	// thrower interface
	RtreeIndexAlreadyExists(const std::string &throwLocation, const std::string &msg)
			: GSTRuntimeException(throwLocation, msg, RTREEINDEXALREADYEXISTS)
	{
	}

	virtual ~RtreeIndexAlreadyExists() throw()
	{
	}
};

class GeometryRejectedByAreaLimiter : public GSTRuntimeException
{
public:
	// thrower interface
	GeometryRejectedByAreaLimiter(const std::string &throwLocation,
								  const std::string &msg)
		: GSTRuntimeException(throwLocation, msg)
	{
	}

	virtual ~GeometryRejectedByAreaLimiter() noexcept
	{
	}
};

} // namespace exceptions
} // namespace GST

#endif //_GSTRUNTIMEEXCEPTION_H_
